package com.hxzy.controller.front;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeWapPayModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeWapPayRequest;
import com.hxzy.common.controller.BaseController;
import com.hxzy.common.enums.AckCode;
import com.hxzy.entity.Orders;
import com.hxzy.exception.ServiceException;
import com.hxzy.service.OrdersService;
import io.swagger.annotations.Api;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;

/**
 * https://opendocs.alipay.com/common/02kkv7  文档
 */
@Log4j2
@Api(tags = "阿里支付API")
@Controller
@RequestMapping(value = "/front/alipay")
public class AlipayController extends BaseController {

    /**
     * 应用ID,您的APPID，收款账号既是您的APPID对应支付宝账号
     */
    public static String app_id = "2016090900469277";

    /**
     * 商户私钥，您的PKCS8格式RSA2私钥  (应用私钥)
     */
    public static String merchant_private_key = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCdug317HHI+PtQEBpua8upW9WlC+inm29Uiw7cU5n/H5/Dgemot0kW/u41H33VnCsqes3Hv+hP/nMarB70h9HWuMrurYoJ70s4MjIBkaIc+QwIKJ+9+xluJcsS/enle9LyvBiEINhOzHqWGE/O60w3KY2ALru3ZcQ6F/+jrOrTsb8YZrcn4Hf+60lo82K7qObMK4VxN1ibq5wkOwUQBvtM8kX6/7a+1ALbXh0+9mOBFY1GXTApTLDkElJM89OtYM7YvApyoDlB4dRLEuJhnAdlzliqbYyN/aeZfpOA+9iEgZtKn7oEOZxSdUV8Yizl0ZHki9MtMDxt0b0QiBD5ab+zAgMBAAECggEAZ8MAcCqOaHIzkmYlnULZBp9dm2iMM8czpGCe9B8jjgzV455RgyagtLodJ2GCPMayNw321lPPluCEBKX6709yolmLVx1fVE3SJDQRZarTBVBps+xVunu4LRg70lCsUMX27q0DS9j3tE8cziVMS4nL5/Y0GoGkCHCweK9VA+47xet+gue5d0eGJmXvvRgYpy5vhQJl9dI924Tvj4Ja+/YpQXDNgoZL60DFOxb3AcgDRmwCAC2Ywyasc8krLtJ2Lun0bMIUuM2CsLQdAUiJdOvmfNaAQvkZsEECG7p5cnUxAKQp9bTz1YhxjoPkO1v4mvA9gj/HP5SY9aTXufZ+t9zcQQKBgQDQnVz3B0gfUravgdSLaMUJgKGVwoBU6nFf0vBqkma4YHBY8XsKBPFxDEzjGW7uIey8P5XUU1THEsk/G5bKqcbVhW18ZWQIWtwYPknbShTXTYBuD27hbShHEuZOdBZhT77lilbP9N5YFgD0d6oOx18bfChEswMwzU/sokw+B+b7QwKBgQDBjaI6yIhOVF+yUA2lmvrQyyEtQW93a57Zqklvzu5DqZnEKm0omiA5aJSkCTM1HGA8pyjf7Ce59+sue5ZdNwuXN72nOPWVFTOQVv948gp8oMuftbfsF04jBKldC5MKgr1yD8MXk2wWcEU5yFTEejExMcoj2duTimJcF+7j+IIK0QKBgQDKoV9QTtFeI3BxLzFtLBnfLgNFvQP79zCie/ir+4Is6veVXRE+3ShLvz/bgrO+OFODUlvNPhflubiiRMEGHzyT36NGJhGxD9gi8DW6+80ciBoMTY9NBUMPLitn3thyMwxgVywVmGpzswPAcY9MBZm6z7EpcZvSxkowtkBKLFDOkwKBgQC1D4RyTwNLmxxGVyLdB2SYC12G006tvSxFXEoEYOR8wVxJqJKix8NbUNyzsrOHfHr+YjUXe/gRvLzxp8UagBLEq+0rUFpT0xiAbxHflzR+L4EsbzaVkZuToJm6o8gyrekAmYQcOtmDCBWKH0BE6DW6WmRJM1R36Z1nny/nbKJh8QKBgDA58P+pscpk1IhsdqEnis4SrlOIC4LdURzg+5QRPAnVTv4CVePVfWhe7i/utFh+6FMVyhjFxRtwzEzu1Jh0Pbk00bWk56NvqSxc/Y2Ca4cX3xrwN88/+q8Dzyw28NMcfjzpvzbSZ37eJxpU6x8EHfJ/KlXeGrTQx03N8C0xfT7E";

    /**
     * 支付宝公钥,查看地址：https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。
     */
    public static String alipay_public_key = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqN+EFOOCU6vVocDruyjwInGWLIX/yhzKCDBit5fCSiAmxSnkhSgZgyA12OESsB1Q79BxhRskDZeV/K6hQLkWNp/Ow9S5vNh15IZtJDZ2XdkS08A/QYxAhVXaFkR0irqVd3s2NI29Fh+cDBujWN5dp8RsRNLcZo7lQ9XywCXkUCyBBx3sChK+vJ78/fBm+4Z4h7eRWYKOt1FyUeE+H6VZT/0Xz2oSrT2rvh6nm9ty6EuDlZrqurL6euc8R9ejzhZ38RvACHm4SkbWfKHyVnQ0oURo4LNNsfEFqNkhmeAx7kw6vEAWpk/FlS/AjlKfTM0xKji98S+Li106sjNw867a+wIDAQAB";

    /**
     *  服务器异步通知页面路径  需http://格式的完整路径，不能加?id=123这类自定义参数，必须外网可以正常访问
     *  这里地址为，支付成功之后回调的地址，异步地址 (阿里云，腾讯云，  内部系统 [花生壳,netapp] )
      */
    public static String notify_url = "http://8frzpm.natappfree.cc/front/alipay/returnUrl";

    /**
     *  页面跳转同步通知页面路径 需http://格式的完整路径，不能加?id=123这类自定义参数，必须外网可以正常访问
     *  这里地址为，支付成功之后跳转的地址，同步
      */

    public static String return_url = "http://localhost/page/user.html";

    // 签名方式
    public static String sign_type = "RSA2";

    // 字符编码格式
    public static String charset = "utf-8";

    public static String format="JSON";

    /**
     * 支付宝网关(沙箱)
     */
    public static String gatewayUrl = "https://openapi.alipaydev.com/gateway.do";

    @Autowired
    private OrdersService ordersService;

    /**
     * 调用支付接口
     *
     * @param orderNumber 订单号
     * @return
     * @throws AlipayApiException
     */
    @RequestMapping("/{orderNumber}")
    public void alipay(@PathVariable("orderNumber") String orderNumber , HttpServletResponse response) throws AlipayApiException, IOException, IOException {

        //https://opendocs.alipay.com/open/02ekfj
        //根据订单号来查询订单
        Orders orders= this.ordersService.findByOrderNumber(orderNumber);
        if(orders==null){
            throw new ServiceException(AckCode.NOT_FOUND_DATA);
        }

        //订单不是未支付状态
        if(orders.getStatus()!=1){
            log.error(orderNumber+",订单状态:"+ orders.getStatus());
            throw new ServiceException(AckCode.ORDER_STATUA_ERROR);
        }

        //调用支付宝逻辑

        //调用封装好的方法（给支付宝接口发送请求）
        String html = sendRequestToAlipay(orderNumber, orders.getAmount().floatValue(), "外卖下单");

        //设定输出格式为html的
        response.setContentType("text/html;charset=" + charset);
        PrintWriter out=response.getWriter();
        out.println(html);
        out.flush();
        out.close();
    }


    /**
     * 支付宝发起下订单请求 订单号
     *
     * @param outTradeNo 订单号
     * @param totalAmount 订单金额
     * @param subject     订单名称
     * @return
     * @throws AlipayApiException
     */
    private String sendRequestToAlipay(String outTradeNo, Float totalAmount, String subject) throws AlipayApiException {

        //实例化阿里客户端 String serverUrl, String appId, String privateKey, String format,
        //                               String charset, String alipayPublicKey, String signType

        //公共请求参数  https://opendocs.alipay.com/open/02ekfj#%E5%85%AC%E5%85%B1%E8%AF%B7%E6%B1%82%E5%8F%82%E6%95%B0
        AlipayClient alipayClient = new DefaultAlipayClient(gatewayUrl,app_id,merchant_private_key,format,charset,alipay_public_key,sign_type);

        //设置请求参数  https://opendocs.alipay.com/open/02ekfj#%E8%AF%B7%E6%B1%82%E5%8F%82%E6%95%B0

        //APP的不能用的
        // AlipayTradeAppPayRequest alipayRequest=new AlipayTradeAppPayRequest();

        //手机网站
        AlipayTradeWapPayRequest alipayRequest=new AlipayTradeWapPayRequest();

        // 电脑网站
        // AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();

        //支付成功了，最终跳转界面 (一般跳转订单页面   或   首页)
        alipayRequest.setReturnUrl(return_url);

        //支付成功或失败的回调地址,必须要与支付宝的 授权回调地址  一致
        alipayRequest.setNotifyUrl(notify_url);


        // 封装请求支付信息 AlipayTradeWapPayRequest

        AlipayTradeWapPayModel model=new AlipayTradeWapPayModel();
        //商家的自定义订单号
        model.setOutTradeNo(outTradeNo);
        //标题
        model.setSubject(subject);
        //金额   单位为元，精确到小数点后两位，取值范围：[0.01  ,   100000000]
        model.setTotalAmount(totalAmount+"");

        //订单附加信息。 如果请求时传递了该参数，将在异步通知、对账单中原样返回，同时会在商户和用户的pc账单详情中作为交易描述展示
        model.setBody(outTradeNo);

        //FAST_INSTANT_TRADE_PAY 代表PC端  电脑网站支付的值是alipay.trade.page.pay    , QUICK_WAP_WAY代表手机端  而手机网站支付的值是alipay.trade.wap.pay
        //model.setProductCode("QUICK_WAP_WAY");
        //设定请求模型
        alipayRequest.setBizModel(model);


        // 执行请求，拿到响应的结果(html)，返回给浏览器
        String form = "";
        try {
            // 调用SDK生成表单 (支付宝生成html页面，调用js执行支付页面)
            form = alipayClient.pageExecute(alipayRequest).getBody();
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }

        log.info("本地生成支付宝的网页代码");
        log.info(form);

        return form;
    }


    /**
     * 阿里同步回调
     *
     * @param request
     * @return
     * @throws AlipayApiException
     * @throws UnsupportedEncodingException
     */
    @RequestMapping("/returnUrl")
    public String returnUrlMethod(HttpServletRequest request) throws AlipayApiException, UnsupportedEncodingException {

        Map<String, String> params = new HashMap<>();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (String name : requestParams.keySet()) {
            params.put(name, request.getParameter(name));
        }

        log.info(requestParams.toString());

        if (request.getParameter("trade_status").equals("TRADE_SUCCESS")) {
            System.out.println("=========支付宝异步回调========");

            String outTradeNo = params.get("out_trade_no");
            String gmtPayment = params.get("gmt_payment");
            String alipayTradeNo = params.get("trade_no");

            // 得到 参数签名
            String sign = params.get("sign");
            // 拿到签名，返回内容进行解密
            String content = AlipaySignature.getSignCheckContentV1(params);
            //拿到内容，再一次加密与支付宝返回的sign进行比较，如果正确，支付没有问题的(数据没有修改过)
            boolean checkSignature = AlipaySignature.rsa256CheckContent(content, sign, AlipayController.alipay_public_key, "UTF-8");
            // 支付宝验签
            if (checkSignature) {
                // 验签通过
                System.out.println("交易名称: " + params.get("subject"));
                System.out.println("交易状态: " + params.get("trade_status"));
                System.out.println("支付宝交易凭证号: " + params.get("trade_no"));
                System.out.println("商户订单号: " + params.get("out_trade_no"));
                System.out.println("交易金额: " + params.get("total_amount"));
                System.out.println("买家在支付宝唯一id: " + params.get("buyer_id"));
                System.out.println("买家付款时间: " + params.get("gmt_payment"));
                System.out.println("买家付款金额: " + params.get("buyer_pay_amount"));

                String orderNumber= params.get("out_trade_no");
                String payTime=params.get("gmt_payment");
                String buyerAmount=params.get("buyer_pay_amount");
                // 更新订单表  支付状态 以及支付方式
                int count=this.ordersService.updatePayStatusByOrderId( orderNumber ,payTime,buyerAmount);

            }else{
                log.error(requestParams.toString());
                throw new ServiceException(AckCode.ORDER_PAY_CheckSignature);
            }
        }else{
            log.error(requestParams.toString());
            throw new ServiceException(AckCode.ORDER_PAY_FAIL);
        }
        //success
        return request.getParameter("trade_status");
    }


}
